#include "common.h"
PUBLIC S4B CreateUserProcess(PPROCESSAFFAIRPARAMETER pparameter)
{
   /*1.We should get the information about the file . */
   FILEDESCRIPTOR filedescriptor;
   MemorySet((PVOID)&filedescriptor,sizeof(FILEDESCRIPTOR),0);
   filedescriptor.path=pparameter->processfilepath;
   if(FSOpenFile(&filedescriptor)!=ARTIST_ERROR_OK)return 1;
  
   DIRECTORYITEM directory;
   filedescriptor.pointer=(POINTER4B)(&directory);
   FSReadDirectory(&filedescriptor);
   
   
   /*2.We should get the information about the elf header.*/
   ELFHEADER elfheader;
   MemorySet((PVOID)(&elfheader),sizeof(ELFHEADER),0);
   filedescriptor.pointer=(POINTER4B)(&elfheader);
   filedescriptor.where.low=0;filedescriptor.where.high=0;
   filedescriptor.howmany.low=sizeof(ELFHEADER);
   filedescriptor.howmany.high=0;
   FSReadFile(&filedescriptor);
 // Print("the header type:%X",elfheader.e_type);
 // Print("the header entry:%X",elfheader.e_entry);
   /*We should prepare the PDE.PTE according to the Program headers.*/
   MMPARAMETER   mmparameter;
   MemorySet((PVOID)(&(mmparameter)),sizeof(MMPARAMETER),0);
   
           /*We need a PCB now.*/
   mmparameter.pagenumber=1;
   MMApplyForPage(&mmparameter);
   PPAGEBLOCK ppcbblock=(mmparameter.blockpointer);
   ApplyForLocking(&mmparameter);
   MemorySet((PVOID)(ppcbblock->page),sizeof(PAGE),0);
 //  Print("the pcb address:%X",ppcbblock->page);
   
           /*We need a PDE now.*/
   mmparameter.pagenumber=1;
   MMApplyForPage(&mmparameter);
   ApplyForLocking(&mmparameter); 

   PPAGEBLOCK ppdeblock= (mmparameter.blockpointer);
   MemorySet((PVOID)(ppdeblock->page),sizeof(PDE),0);
//Print("the pde address:%X",ppdeblock->page);
   
           /*We need a KERNEL PTE now.*/
   mmparameter.pagenumber=1;
   MMApplyForPage(&mmparameter);
   ApplyForLocking(&mmparameter);
   PPAGEBLOCK pkernelpteblock=(mmparameter.blockpointer);
   MemorySet((PVOID)(pkernelpteblock->page),sizeof(PTE),0);
//Print("the pte address:%X",ppteblock->page);
   /*We need a PCB PTE now.*/
   mmparameter.pagenumber=1;
   MMApplyForPage(&mmparameter);
   ApplyForLocking(&mmparameter);
   PPAGEBLOCK ppcbpteblock=(mmparameter.blockpointer);
   MemorySet((PVOID)(ppcbpteblock->page),sizeof(PTE),0);
           /*We initialize the pde pte pcb.*/
   InitUserPDEAndPTE((PPDE)(ppdeblock->page),(PPTE)(pkernelpteblock->page),(PPTE)(ppcbpteblock->page),(PPROCESS)ppcbblock->page);

		   
           /*We need a message buffer now.*/
   mmparameter.pagenumber=1;
   MMApplyForPage(&mmparameter);
   ApplyForLocking(&mmparameter);
   PPAGEBLOCK pmessageblock=mmparameter.blockpointer;
   MemorySet((PVOID)(pmessageblock->page),sizeof(PAGE),0);
//Print("the message address:%X",pmessageblock->page);
		   /*We need a signal     buffer now.*/
   mmparameter.pagenumber=1;
   MMApplyForPage(&mmparameter);
   ApplyForLocking(&mmparameter);
   PPAGEBLOCK psignalblock=mmparameter.blockpointer;
   MemorySet((PVOID)(psignalblock->page),sizeof(PAGE),0);
//Print("the signal address:%X",psignalblock->page);
		   /*We need a stack      buffer now.*/
   mmparameter.pagenumber=1;
   MMApplyForPage(&mmparameter);
   ApplyForLocking(&mmparameter);
   PPAGEBLOCK pstackblock=mmparameter.blockpointer;
   MemorySet((PVOID)(pstackblock->page),sizeof(PAGE),0);
//Print("the stack address:%X",pstackblock->page);
//Print("pindex:%X  ",pidnext);
   InitUserPCB(
                  (PPROCESS)(ppcbblock->page),
                   pidnext,
                   (PVOID)elfheader.e_entry,
                   (U4B)(pstackblock->page),
   	           (PVOID)(pmessageblock->page),
                   (PVOID)(psignalblock->page),10,
                   (directory.e_name),
   	           (PPDE)(ppdeblock->page),
                   (PPROCESS)NULL,(PPROCESS)NULL);
   pidnext++;

   
   /*We should get the information about the program header.*/

   
   /*We should load the binary code now.*/
   U2B ph;
   PROGRAMHEADER programheader;
   
   for(ph=0;ph<elfheader.e_programheadernumber;ph++)
   {     
       filedescriptor.pointer=(POINTER4B)(&programheader);
	   filedescriptor.where.low=elfheader.e_programheaderoffset+ph*sizeof(PROGRAMHEADER);
	   filedescriptor.where.high=0;
	   filedescriptor.howmany.high=0;filedescriptor.howmany.low=sizeof(PROGRAMHEADER);
	   FSReadFile(&filedescriptor);	   
 //Print("file descriptor:%X",filedescriptor.);

       //    Print("programheader p_type %X ",programheader.p_type);
	   if(programheader.p_type!=ELF_RROGRAMHEADER_LOADABLE_TYPE)
	   	continue;
         //  Print("programheader p_virtualaddress %X ",programheader.p_virtualaddress);
	   U4B offset=programheader.p_offset;
	   U4B memstart,memend;
	   memstart=programheader.p_virtualaddress;
	   memend  =memstart+programheader.p_memorysize-1;
        //   Print("memstart:%X,memend:%X",memstart,memend);
       U4B pdex,pdey,ptex,ptey,offsetx,offsety;
	   pdex=memstart>>22;          pdey=memend>>22;
	   ptex=(memstart>>12)&0x3FF;  ptey=(memend>>12)&0x3FF;
	   offsetx=memstart&0xFFF;     offsety=memend&0xFFF;
//Print("pdex:%X,pdey:%X,ptex:%X,ptey:%X,offsetx:%X,offsety:%X \n",pdex,pdey,ptex,ptey,offsetx,offsety);

	   U4B pdetemp=pdex;
	   for(;pdetemp<=pdey;pdetemp++)
	   {
	        if(((ppdeblock->page->room[pdetemp])&0xFFFFF000)==0)//PTE NOT OK
	        {//Print("ok,i am here.");
                    //   Print("pde:%X ",pdetemp);
	               mmparameter.pagenumber=1;
                   MMApplyForPage(&mmparameter);
                   ApplyForLocking(&mmparameter);
                   //Print("pte address:%X",mmparameter.blockpointer->page);
				   MemorySet((PVOID)(mmparameter.blockpointer->page),sizeof(PTE),0);
				   ppdeblock->page->room[pdetemp]=(U4B)(mmparameter.blockpointer->page)+0x7;
//Print("ppdeblock->page->room[pdetemp]:%X",ppdeblock->page->room[pdetemp]);
	        }
			U4B ptes,ptee;
			if(pdetemp==pdex)
			{ptes=ptex;}
			else
			{ptes=0;}
			if(pdetemp==pdey)
			{ptee=ptey;}
			else
			{ptee=1023;}

                      // Print("ptes:%X,ptee:%X",ptes,ptee);
			U4B ptetemp;
			ptetemp=ptes;
			PPTE ptelocal=(PPTE)((ppdeblock->page->room[pdetemp])&0xFFFFF000);
            // Print("ptelocal:%X",ptelocal);
			for(;ptetemp<=ptee;ptetemp++)
			{
			   if(((ptelocal->pte[ptetemp])&0xFFFFF000)==0) //PAGE NOT OK
			   {//Print("ok,i am here.");
			       mmparameter.pagenumber=1;
				   MMApplyForPage(&mmparameter);
				  // ApplyForLocking(&mmparameter);
				   MemorySet((PVOID)(mmparameter.blockpointer->page),sizeof(PAGE),0);
				   ptelocal->pte[ptetemp]=(U4B)(((U4B)(mmparameter.blockpointer->page))&0xFFFFF000)+0x7;
                               //  Print("petlocal->pte[ptetemp]:%X",ptelocal->pte[ptetemp]);
			   }
			   U4B startoffsetlocal,endoffsetlocal;
			   if(pdetemp==pdex && ptetemp==ptex)
			   	{startoffsetlocal=offsetx;}
			   else
			   	{startoffsetlocal=0;}
			   if(pdetemp==pdey && ptetemp==ptey)
			   	{endoffsetlocal=offsety;}
			   else
			   	{endoffsetlocal=sizeof(PAGE)-1;}
			 //  Print("startoffset:%X,endoffset:%X",startoffsetlocal,endoffsetlocal);
			   filedescriptor.pointer=(POINTER4B)((((U4B)(ptelocal->pte[ptetemp]))&0xFFFFF000)+startoffsetlocal);
                 // Print("code destination:%X",filedescriptor.pointer);
			   filedescriptor.where.low=offset;
                           // Print("filedescriptor.where.low:%X",offset);
			   filedescriptor.where.high=0;
			   filedescriptor.howmany.high=0;filedescriptor.howmany.low=endoffsetlocal-startoffsetlocal+1;
          // Print("filedescriptor.howmany.low:%X",filedescriptor.howmany.low);
			   FSReadFile(&filedescriptor);    
                          // Print("code:%X .",*((PU4B)0xa08000));
			   offset+=(endoffsetlocal-startoffsetlocal+1);
			}
			
	   }
   }
   
   
       /*We should set the stack now.I think the stack should start from the 0xFFFFFFFF ,however if necessary ,
	        We can change it.*/
   
	   if(((ppdeblock->page->room[1023])&0xFFFFF000)==0)//PTE NOT OK
	   {
				  mmparameter.pagenumber=1;
				  MMApplyForPage(&mmparameter);
				  ApplyForLocking(&mmparameter);
				  MemorySet((PVOID)(mmparameter.blockpointer->page),sizeof(PTE),0);
				  ppdeblock->page->room[1023]=(U4B)(mmparameter.blockpointer->page)+0x7;
	   }
      PPTE ptelast=(PPTE)((ppdeblock->page->room[1023])&0xFFFFF000);
      ptelast->pte[1023]=((U4B)(pstackblock->page))+0x7;
     // Print(" aaa%X ",ppcbblock->page);
//202450
     // Print("   %X ",ppdeblock->page->room[((U4B)202450)>>22]);
      //Print("   0X40001000: %X",((PPTE)((ppdeblock->page->room[((U4B)0X40001000)>>22])&0xFFFFF000))->pte[(((U4B)0X40001000)>>12)&0x3FF]);
 //Print("here%X ",((PPROCESS)(ppcbblock->page))->p_pid);
      ActivateProcess((PPROCESS)(ppcbblock->page));
   /*We should initialize the PCB.Fill the message buffer and signal buffer.*/
   return 0;
}
